<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            height: 100vh;
            margin: 0;
            padding: 0;
            display: -webkit-box;
            display: flex;
            -webkit-box-pack: center;
            justify-content: center;
            -webkit-box-align: center;
            align-items: center;
            font-weight: 400;
            font-size: 22px;
            background: #000;
            color: #fff;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
        }

        .word {
            position: relative;
            z-index: 1;
            font-family: 'Titillium Web', sans-serif;
        }

        .word:before {
            content: '';
            background: radial-gradient(circle at 40% 20%, #fcfcfc 0%, #ddd 10%, #333 50%, black 70%);
            border-radius: 50%;
            width: 80px;
            height: 80px;
            position: absolute;
            z-index: 1;
            left: 50%;
            top: 50%;
            -webkit-transform: translate(-40%, -35%);
            transform: translate(-40%, -35%);
            -webkit-filter: blur(0.5px);
            filter: blur(0.5px);
        }

        span {
            position: absolute;
            z-index: 1;
            top: 0;
            left: 0;
        }
    </style>
</head>

<body>
    <div class="word">SPACE INVADERS </div>

    <script>
        /*--------------------
Vars
--------------------*/
        let time = 0
        let mouseX = window.innerWidth * 0.75
        let x = 0


        /*--------------------
        Options
        --------------------*/
        const opt = {
            radius: 100,
            radiusY: 0.4,
            maxSpeed: 0.05,
            maxRotation: 50,
            minOpacity: 0.3,
            spacer: '*'
        }


        /*--------------------
        Utils
        --------------------*/
        const scale = (a, b, c, d, e) => {
            return (a - b) * (e - d) / (c - b) + d
        }
        const lerp = (v0, v1, t) => {
            return v0 * (1 - t) + v1 * t
        }


        /*--------------------
        Create Invaders
        --------------------*/
        const createInvaders = () => {
            const word = document.querySelector('.word')
            const Letters = word.innerHTML.replace(/\s/g, opt.spacer).split('').reverse()
            word.innerHTML = ''
            Letters.forEach(i => {
                const l = document.createElement('span')
                l.innerHTML = i
                word.appendChild(l)
            })
        }
        createInvaders()
        const letter = document.querySelectorAll('.word span')


        /*--------------------
        Animate
        --------------------*/
        const animate = () => {
            if (!letter) return

            x = lerp(x, mouseX / window.innerWidth, 0.1)
            const rotation = -opt.maxRotation + x * opt.maxRotation * 2
            const speed = (-opt.maxSpeed + x * opt.maxSpeed * 2)
            const modY = 1 + x * -2

            time -= speed

            letter.forEach((i, ind) => {
                const theta = 1 - ind / letter.length
                const x = opt.radius * Math.sin(time + theta * Math.PI * 2)
                const y = opt.radius * opt.radiusY * Math.cos(modY + time + theta * Math.PI * 2)
                const s = scale(y, -opt.radius * opt.radiusY, opt.radius * opt.radiusY, opt.minOpacity, 1)

                Object.assign(i.style, {
                    zIndex: Math.min(2, Math.max(-2, Math.ceil(y))),
                    filter: `blur(${4 - 5 * s}px)`,
                    opacity: s,
                    transform: `translate3d(${x}px, ${y}px, 0) rotate(${rotation}deg)`
                })

            })
            requestAnimationFrame(animate)
        }
        animate()


        /*--------------------
        Events
        --------------------*/
        const handleMouse = e => {
            mouseX = e.clientX || e.touches[0].clientX
        }
        window.addEventListener('mousemove', handleMouse)
        window.addEventListener('touchstart', handleMouse)
        window.addEventListener('touchmove', handleMouse)

    </script>
</body>

</html>